#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/5/17 14:57
# @Author  : Grayson Liu
# @Email   : graysonliu@foxmail.com
# @File    : cpu2017.py

import re
from typing import Union
import pandas as pd


def company_rule(x: str) -> str:
    """
    对Company这一列数据的处理操作，用于DataFrame的map方法
    :param x: Company属性的值
    :return: 处理后的值
    """
    y = x.replace(",", "")  # 去除逗号
    y = re.sub(r"GIGA-BYTE TECHNOLOGY CO. LTD$", "GIGA-BYTE TECHNOLOGY CO. LTD.", y)  # 正则表达式替换：\b匹配单词边界，$匹配字符串末尾
    y = y.strip()  # 去除前后空格
    return y


# 4.2.7 Cache
# 4.2.7.1 1st Cache
def first_cache_rule(x: str) -> str:
    """
    对1st Cache这一列数据的处理操作，用于DataFrame的map方法
    :param x: 1st Cache属性的值
    :return: 处理后的1st Cache per core(KB)值
    """
    if x.find("per core") != -1:
        # 说明：(group1: 1个以上数字)+可能有空格+'KB'+可能有空格+I'+可能有空格+'+'+可能有空格+(group2: 1个以上数字)+可能有空格+'KB'+可能有空格+'D'
        search_obj = re.match(r"(\d+)\s*KB\s*I\s*\+\s*(\d+)\s*KB\s*D", x)
        l1i_kb = search_obj.group(1)
        l1d_kb = search_obj.group(2)
        return f"{l1i_kb}KB(I)+{l1d_kb}KB(D)"
    elif x.find("redacted") != -1:
        return "0"
    else:
        # 说明：(group1: 1个以上数字)+可能有空格+'KB'
        search_obj = re.match(r"(\d+)\s*KB", x)
        l1_kb = search_obj.group(1)
        return f"{l1_kb}KB(I+D)"


# 4.2.7.2 2nd Cache
def second_cache_rule(line: pd.Series) -> str:
    """
    对2nd Cache这一列数据的处理操作，用于DataFrame的apply方法（需要用到其他属性的值）
    :param line: DataFrame的一行，类型是pd.Series
    :return: 处理后的2nd Cache per core(KB)值
    """
    x = line["2nd Cache per core(KB)"]
    cores_num = line["# cores"]
    chips_num = line["# chips"]
    if x.find("I+D") != -1:
        if x.find("per core") != -1:
            if x.find("KB") != -1:  # eg. 256 KB I+D on chip per core
                search_obj = re.match(r"(\d+)\s*KB", x)
                l2_kb = search_obj.group(1)
                return f"{l2_kb}KB(I+D)"
            else:  # eg. 1 MB I+D on chip per core
                search_obj = re.match(r"(\d+(\.\d+)?)\s*MB", x)
                l2_kb = int(float(search_obj.group(1)) * 1024)
                return f"{l2_kb}KB(I+D)"
        elif x.find("per chip") != -1:  # eg. 2 MB I+D on chip per chip
            search_obj = re.match(r"(\d+)\s*MB", x)
            l2_kb = int(int(search_obj.group(1)) * 1024 * chips_num / float(cores_num))
            return f"{l2_kb}KB(I+D)"
    else:
        if x.find("redacted") != -1:
            return "0"
        else:
            # 说明：(group1: 1个以上数字)+可能有空格+'KB'+可能有空格+I'+可能有空格+'+'+可能有空格+(group2: 1个以上数字)+可能有空格+'KB'+可能有空格+'D'
            # eg. 2 MB I on chip per chip (256 KB / 4 cores); 4 MB D on chip per chip (256 KB / 2 cores)
            search_obj = re.match(r"(\d+)\s*MB\s*I.*(\d+)\s*MB\s*D", x)
            l1i_kb = int(int(search_obj.group(1)) * 1024 * chips_num / float(cores_num))
            l1d_kb = int(int(search_obj.group(2)) * 1024 * chips_num / float(cores_num))
            return f"{l1i_kb}KB(I)+{l1d_kb}KB(D)"


# 4.2.7.3 3rd Cache
def third_cache_rule(line: pd.Series) -> str:
    """
    对3rd Cache这一列数据的处理操作，用于DataFrame的apply方法（需要用到其他属性的值）
    :param line: DataFrame的一行，类型是pd.Series
    :return: 处理后的3rd Cache per chip(MB)值
    """
    x = line["3rd Cache per chip(MB)"]
    cores_num = line["# cores"]
    chips_num = line["# chips"]
    if x.find("I+D") != -1:
        if x.find("per core") != -1:
            if x.find("on chip per core") != -1:  # eg. 8 MB I+D on chip per core
                search_obj = re.match(r"(\d+)\s*MB", x)
                l2_mb = int(int(search_obj.group(1)) * cores_num / float(chips_num))
                return f"{l2_mb}MB"
            elif x.find("on chip per chip") != -1:  # eg. 128 MB I+D on chip per chip, 16 MB per core
                search_obj = re.match(r"(\d+(\.\d+)?)\s*MB\s*I\+D", x)
                l2_mb = search_obj.group(1)
                return f"{l2_mb}MB"
        else:  # eg. 256 MB I+D on chip per chip, 16 MB shared / 4 cores
            search_obj = re.match(r"(\d+(\.\d+)?)\s*MB\s*I\+D", x)
            l2_mb = search_obj.group(1)
            return f"{l2_mb}MB"
    else:
        if x.find("redacted") != -1:
            return "0"
        else:
            # 说明：(group1: 1个以上数字)+可能有空格+'MB'
            search_obj = re.match(r"(\d+)\s*MB", x)
            l1_mb = search_obj.group(1)
            return f"{l1_mb}MB"


# 4.2.7.4 other Cache
def other_cache_rule(x: str) -> str:
    """
    对other Cache这一列数据的处理操作，用于DataFrame的map方法
    :param x: other Cache属性的值
    :return: 处理后的other Cache per chip(MB)值
    """
    if x.find("None") != -1:
        return "0"
    else:  # eg. 16 MB I+D off chip per 8 DIMMs
        search_obj = re.match(r"(\d+(\.\d+)?)\s*MB\s*I\+D", x)
        l2_mb = search_obj.group(1)
        return f"{l2_mb}MB"


# 4.2.8 Memory
def memory_rule(x: str) -> str:
    """
    对Memory这一列数据的处理操作，用于DataFrame的map方法
    :param x: Memory属性的值
    :return: 处理后的Memory(GB)值
    """
    y = re.sub(r"\(.*\)", "", x)  # 删除括号中的内容
    y = y.rstrip()  # 删除末尾的空格
    if y.find("MB") != -1:
        search_obj = re.match(r"(\d+)\s*MB", y)
        memory_gb = int(int(search_obj.group(1)) / 1024.0)
        return f"{memory_gb}GB"
    elif y.find("GB") != -1:
        search_obj = re.match(r"(\d+)\s*GB", y)
        return f"{search_obj.group(1)}GB"
    elif y.find("TB") != -1:
        search_obj = re.match(r"(\d+)\s*TB", y)
        memory_gb = int(int(search_obj.group(1)) * 1024)
        return f"{memory_gb}GB"
    else:
        return f"{int(int(y) / 1024.0)}GB"


def report_link_rule(x: str) -> str:
    """
    对Disclosure这一列数据的处理操作，用于DataFrame的map方法
    :param x: Disclosure属性的值
    :return: 处理后的Report Link值
    """
    search_obj = re.match(r'<A HREF="(.*)">HTML</A>',x)
    return f"https://www.spec.org{search_obj.group(1)}"